package net.m3u8.main;

import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import net.m3u8.common.exception.M3u8Exception;
import net.m3u8.common.factory.M3u8DownloadFactory;
import net.m3u8.common.listener.DownloadListener;
import net.m3u8.common.utils.MediaFormat;
import net.m3u8.common.utils.StringUtils;
import org.apache.log4j.Logger;
import org.jb2011.lnf.beautyeye.BeautyEyeLNFHelper;
import org.jb2011.lnf.beautyeye.ch3_button.BEButtonUI;

import javax.swing.*;
import javax.swing.filechooser.FileSystemView;
import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.net.MalformedURLException;

/**
 * 主界面
 * @author daixf
 * @date 2020/3/8
 */
public class MainFrame {
    public final static Logger logger = Logger.getLogger(MainFrame.class);

    private JFrame frame;
    private JTextField tf_file_path;
    private File openFile;
    private JTextField tf_m3u8_url; //index.m3u8的url
    private JTextField tf_file_name; //保存的视频文件名，不带后缀名
    private JTextField tf_thread_count;//线程数
    private JTextField tf_retry_count;//重试次数
    private JTextField tf_timeout;//连接超时时间（单位：毫秒）
    private JLabel lbl_process;
    private JProgressBar progressBar;
    private JLabel lbl_speed;
    private JButton btn_download;
    private AudioClip audioClip;

    public static void main(String[] args) throws Exception {
        BeautyEyeLNFHelper.frameBorderStyle = BeautyEyeLNFHelper.FrameBorderStyle.generalNoTranslucencyShadow;
        //设置此开关量为false即表示关闭之，BeautyEye LNF中默认是true
        BeautyEyeLNFHelper.translucencyAtFrameInactive = false;
        BeautyEyeLNFHelper.launchBeautyEyeLNF();
        UIManager.put("RootPane.setupButtonVisible", false);

        MainFrame mainFrame = new MainFrame();
        mainFrame.initUI();
    }

    public void initUI() throws MalformedURLException {
        frame = new JFrame("M3u8视频下载器 Created By 黎瑛");
        frame.setBounds(100, 100, 670, 310);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //设置应用左上角的icon
        frame.setIconImage(new ImageIcon("resources/images/download.png").getImage());
        frame.setResizable(false);
        frame.setLayout(null);

        audioClip = Applet.newAudioClip(new File("resources/audios/download-complete.wav").toURI().toURL());//下载完成的音频

        Font font = new Font("微软雅黑", Font.PLAIN, 14);
        Font btnFont = new Font("微软雅黑", Font.BOLD, 13);

        //index.m3u8的视频地址
        JLabel lbl_m3u8_url = new JLabel("视频地址：");
        addJLabel(lbl_m3u8_url, font, JLabel.RIGHT, 0, 10, 120, 35);

        tf_m3u8_url = new JTextField();
        addJTextField(tf_m3u8_url, font, JTextField.LEFT, 125, 13, 500, 30, "");

        //保存目录
        JLabel lbl_file = new JLabel("保存目录：");
        addJLabel(lbl_file, font, JLabel.RIGHT, 0, 50, 120, 35);

        tf_file_path = new JTextField();
        addJTextField(tf_file_path, font, JTextField.LEFT, 125, 53, 410, 30, "F:/Downloads/Videos/福尔摩斯探案集");

        JButton btn_browse = new JButton("选择目录");
        addButton(btn_browse, btnFont, BEButtonUI.NormalColor.lightBlue, 545, 53, 80, 30, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                FileSystemView fsv = FileSystemView.getFileSystemView();
                File defaultFolder = fsv.getHomeDirectory();
                if(StrUtil.isNotBlank(tf_file_path.getText())) {
                    defaultFolder = new File(tf_file_path.getText());
                }

                JFileChooser chooser = new JFileChooser(defaultFolder); //文件选择
                chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                chooser.showOpenDialog(chooser);        //打开文件选择窗
                openFile = chooser.getSelectedFile();  	//获取选择的文件
                if(openFile != null) {
                    tf_file_path.setText(openFile.getPath());//获取选择文件的路径
                }
            }
        });

        //保存的视频文件名，不带后缀名
        JLabel lbl_file_name = new JLabel("保存文件名：");
        addJLabel(lbl_file_name, font, JLabel.RIGHT, 0, 90, 120, 35);

        tf_file_name = new JTextField();
        addJTextField(tf_file_name, font, JTextField.LEFT, 125, 93, 220, 30, "");
        tf_file_name.setText("福尔摩斯探案集");

        //线程数
        JLabel lbl_thread_count = new JLabel("线程数：");
        addJLabel(lbl_thread_count, font, JLabel.RIGHT, 345, 90, 120, 35);

        tf_thread_count = new JTextField();
        addJTextField(tf_thread_count, font, JTextField.LEFT, 465, 93, 160, 30, "100");

        //重试次数
        JLabel lbl_retry_count = new JLabel("重试次数：");
        addJLabel(lbl_retry_count, font, JLabel.RIGHT, 0, 130, 120, 35);

        tf_retry_count = new JTextField();
        addJTextField(tf_retry_count, font, JTextField.LEFT, 125, 133, 220, 30, "50");

        //连接超时时间（单位：毫秒）
        JLabel lbl_timeout = new JLabel("连接超时时间：");
        addJLabel(lbl_timeout, font, JLabel.RIGHT, 345, 130, 120, 35);

        tf_timeout = new JTextField();
        addJTextField(tf_timeout, font, JTextField.LEFT, 465, 133, 120, 30, "10");
        addJLabel(new JLabel("（秒）"), font, JLabel.LEFT, 585, 130, 50, 35);

        //开始下载按钮
        btn_download = new JButton("开始下载");
        addButton(btn_download, btnFont, BEButtonUI.NormalColor.green, 180, 180, 80, 30, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                downloadM3u8Video();
            }
        });

        //清空按钮
        JButton btn_clear = new JButton("清       空");
        addButton(btn_clear, btnFont, BEButtonUI.NormalColor.red, 280, 180, 80, 30, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                tf_file_path.setText("");
                tf_m3u8_url.setText("");
                tf_file_name.setText("");
                tf_thread_count.setText("100");
                tf_retry_count.setText("50");
                tf_timeout.setText("10");
            }
        });

        //退出按钮
        JButton btn_exit = new JButton("退       出");
        addButton(btn_exit, btnFont, BEButtonUI.NormalColor.red, 380, 180, 80, 30, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });

        lbl_process = new JLabel("下载进度：");
        addJLabel(lbl_process, font, JLabel.RIGHT, 0, 220, 120, 35);
        lbl_process.setVisible(false);

        progressBar = new JProgressBar(JProgressBar.HORIZONTAL, 0, 100);
        progressBar.setBounds(125, 230, 420, 20);
        progressBar.setStringPainted(true);
        progressBar.setVisible(false);
        frame.add(progressBar);

        lbl_speed = new JLabel("");
        addJLabel(lbl_speed, new Font("微软雅黑", Font.PLAIN, 12), JLabel.LEFT, 555, 220, 90, 35);
        lbl_speed.setVisible(false);

        frame.setVisible(true);
    }

    /**
     * 校验字段
     * @return
     */
    public boolean checkFields() {
        String m3u8_url = tf_m3u8_url.getText();
        String file_path = tf_file_path.getText();
        String file_name = tf_file_name.getText();
        String thread_count = tf_thread_count.getText();
        String retry_count = tf_retry_count.getText();
        String timeout = tf_timeout.getText();

        if(StrUtil.isBlank(m3u8_url)) {
            JOptionPane.showMessageDialog(null, "请填写视频地址！", "警告", JOptionPane.ERROR_MESSAGE);
            return false;
        }
        if ("m3u8".compareTo(MediaFormat.getMediaFormat(m3u8_url)) != 0) {
            JOptionPane.showMessageDialog(null, m3u8_url+"不是一个完整m3u8链接！", "警告", JOptionPane.ERROR_MESSAGE);
            btn_download.setEnabled(true);
            return false;
        }
        if(StrUtil.isBlank(file_path)) {
            JOptionPane.showMessageDialog(null, "请选择或输入保存目录！", "警告", JOptionPane.ERROR_MESSAGE);
            btn_download.setEnabled(true);
            return false;
        }
        if(!file_path.endsWith("/")) {//保存目录设置为以“/”结尾
            file_path = file_path+"/";
        }
        if(StrUtil.isBlank(file_name)) {
            JOptionPane.showMessageDialog(null, "保存文件名不得为空！", "警告", JOptionPane.ERROR_MESSAGE);
            btn_download.setEnabled(true);
            return false;
        }
        if(StrUtil.isBlank(thread_count)) {
            JOptionPane.showMessageDialog(null, "线程数不得为空！", "警告", JOptionPane.ERROR_MESSAGE);
            btn_download.setEnabled(true);
            return false;
        }
        if(!ReUtil.isMatch("^[1-9]\\d*$", thread_count)) {
            JOptionPane.showMessageDialog(null, "线程数必须为正整数！", "警告", JOptionPane.ERROR_MESSAGE);
            btn_download.setEnabled(true);
            return false;
        }
        if(StrUtil.isBlank(retry_count)) {
            JOptionPane.showMessageDialog(null, "重试次数不得为空！", "警告", JOptionPane.ERROR_MESSAGE);
            return false;
        }
        if(!ReUtil.isMatch("^\\d+$", retry_count)) {
            JOptionPane.showMessageDialog(null, "重试次数必须为大于或等于0的整数！", "警告", JOptionPane.ERROR_MESSAGE);
            return false;
        }
        if(StrUtil.isBlank(timeout)) {
            JOptionPane.showMessageDialog(null, "连接超时时间不得为空！", "警告", JOptionPane.ERROR_MESSAGE);
            return false;
        }
        if(!ReUtil.isMatch("^[1-9]\\d*$", timeout)) {
            JOptionPane.showMessageDialog(null, "连接超时时间必须为正整数！", "警告", JOptionPane.ERROR_MESSAGE);
            return false;
        }
        return true;
    }

    /**
     * 下载视频
     */
    public void downloadM3u8Video() {
        btn_download.setEnabled(false);

        //校验字段
        if(!checkFields()) {
            btn_download.setEnabled(true);
            return;
        }

        String file_path = tf_file_path.getText();
        if(!file_path.endsWith("/")) {//保存目录设置为以“/”结尾
            file_path = file_path+"/";
        }

        progressBar.setString("正在解析视频地址，请稍后...");
        lbl_process.setVisible(true);
        progressBar.setVisible(true);
        lbl_speed.setVisible(true);

        M3u8DownloadFactory.M3u8Download m3u8Download = M3u8DownloadFactory.getInstance(tf_m3u8_url.getText());
        //设置生成目录
        m3u8Download.setDir(file_path);
        //设置视频名称
        m3u8Download.setFileName(tf_file_name.getText());
        //设置线程数
        m3u8Download.setThreadCount(Integer.parseInt(tf_thread_count.getText()));
        //设置重试次数
        m3u8Download.setRetryCount(Integer.parseInt(tf_retry_count.getText()));
        //设置连接超时时间（单位：毫秒）
        m3u8Download.setTimeoutMillisecond(Long.parseLong(tf_timeout.getText())*1000);
        //设置监听器间隔（单位：毫秒）
        m3u8Download.setInterval(1000L);
        //添加监听器
        m3u8Download.addListener(new DownloadListener() {
            @Override
            public void prepare(int step, String msg) {
                logger.info("正在解析视频地址，请稍后...");
                progressBar.setString(msg);
            }

            @Override
            public void start(int sum) {
                logger.info("检测到"+sum+"个视频片段，开始下载！");
                progressBar.setMaximum(sum);
                progressBar.setValue(0);
                progressBar.setString("0% (0/"+sum+")");
            }

            @Override
            public void process(String downloadUrl, int finished, int sum, float percent) {
                logger.info("已下载" + finished + "个\t一共" + sum + "个\t已完成" + percent + "%");
                progressBar.setValue(finished);
                progressBar.setString(percent+"% ("+finished+"/"+sum+")");
            }

            @Override
            public void speed(String speedPerSecond) {
                logger.info("下载速度：" + speedPerSecond);
                lbl_speed.setText(speedPerSecond);
            }

            @Override
            public void end() {
                logger.info("下载完毕");
                lbl_speed.setText("");
                progressBar.setString("视频下载完毕");
                audioClip.play();//播放下载完成的音频
                JOptionPane.showMessageDialog(null, "视频下载完毕！", "提醒", JOptionPane.INFORMATION_MESSAGE);
                btn_download.setEnabled(true);
            }
        });

        //开始下载
        m3u8Download.runTask();
    }

    public void addJLabel(JLabel label, Font font, int horizontalAlignment, int x, int y, int width, int height) {
        label.setFont(font);
        label.setHorizontalAlignment(horizontalAlignment);
        label.setBounds(x, y, width, height);
        frame.add(label);
    }

    public void addJTextField(JTextField textField, Font font, int horizontalAlignment, int x, int y, int width, int height, String defaultText) {
        textField.setFont(font);
        textField.setHorizontalAlignment(horizontalAlignment);
        textField.setBounds(x, y, width, height);
        if(defaultText != null && !"".equals(defaultText)) {
            textField.setText(defaultText);
        }
        frame.add(textField);
    }

    public void addButton(JButton button, Font font, BEButtonUI.NormalColor nc, int x, int y, int width, int height, ActionListener listener) {
        button.setFont(font);
        button.setForeground(Color.white);
        button.setBounds(x, y, width, height);
        button.addActionListener(listener);
        button.setUI(new BEButtonUI().setNormalColor(nc));
        frame.add(button);
    }
}